#include "operacionCrear.h"

std::string OperacionCrear::NOMBRE_PARAM_CREAR = "CREAR";	

OperacionCrear::OperacionCrear(ArchivoDatos * a, std::string &f){
	this->archivo = a;
	this->formato_archivo = f;
}

OperacionCrear::~OperacionCrear(){

}

//Funcion privada para eliminar los elementos que usa el vector<TipoDato *>
void liberar( std::vector<TipoDato *>& v){
	std::vector<TipoDato *>::iterator it = v.begin();
	
	while(it != v.end() ){
		delete (*it);
		++it;	
	}
	
}
Operacion * OperacionCrear::construir(std::string param)throw (ExcepSintaxisParser){
	Operacion * _return = NULL;
	if (Parser::procesar_nombre_operacion(param,NOMBRE_PARAM_CREAR)){
		//si tiene los params que necesita el crear y es del tipo
		std::vector<std::string> params = Parser::split_parametros(param, ';');
		if( params.size() == 3){
			std::string nombre_archivo;
			nombre_archivo = Parser::procesar_nombre(params[0]);//reviso el nombre del archivo
			size_t pos = params[1].find_first_of('[');
			if( pos != std::string::npos ){
				//separo los campos
				
				std::string tipo_archivo = params[1].substr(0, pos);
				std::string formato = params[1].substr(pos, params.size() - pos - 1);
				std::vector<TipoDato *> parametros_archivo;
				
				if( (formato[0] == '[') && (formato[formato.size() -1] == ']') ){
					//proceso los parametros
					if( (params[2][0] == '[') && (params[2][params[2].size() -1] == ']') ){
						parametros_archivo = Parser::obtener_datos_atomicos(params[2].substr(1, (params[2].size()) - 2));   
						//si tiene 2 parametros me fijo que sean enteros
						if( parametros_archivo.size() == 2 ){
							if( (parametros_archivo[0]->get_codigo_tipo() == INT) &&
								(parametros_archivo[1]->get_codigo_tipo() == INT) ){
								int tam_bloque = ((TipoInt *)parametros_archivo[0])->get_valor();
								int tam_bloque_ind = ((TipoInt *)parametros_archivo[1])->get_valor(); 
								if( tam_bloque < 32){
									liberar(parametros_archivo);
									throw ExcepSintaxisParser("Error - El tamano del bloque debe ser mayor o igual a 32");
								}
								if( tam_bloque_ind < 48){
									liberar(parametros_archivo);
									throw ExcepSintaxisParser("Error - El tamano del bloque del indice debe ser mayor o igual a 48");
								}
								ArchivoDatos * a;
								ArchivosFactory fab;
								try{
									a = fab.crear_archivo(tipo_archivo, nombre_archivo, tam_bloque, tam_bloque_ind);
								}
								catch(ExcepSintaxisParser &e){
									liberar(parametros_archivo);
									throw e;
								}									
								if(a != NULL)
									_return = new OperacionCrear(a, formato);	
							}
							else{
								liberar(parametros_archivo); 
								throw ExcepSintaxisParser("Error - Los parametros deben ser enteros. ");
							}
						}
						else{
							liberar(parametros_archivo);
							throw ExcepSintaxisParser("Error - Cantidad de parametros invalidos. ");
						}
					}
					else 
						throw ExcepSintaxisParser("Error - Ingreso de formato invalido, los parametros deben estar entre [ ]. ");
					liberar(parametros_archivo);
				}
				else
					throw ExcepSintaxisParser("Error - Formato del archivo incorrecto. Falta un ']' ");
				
			}
			else
				throw ExcepSintaxisParser("Error - Falta el '[' para iniciar el formato del archivo. ");
		}
		else 
			throw ExcepSintaxisParser("Error - Cantidad de parametros incorrectos para la operacion crear. ");
	}
	return _return;
}
	
void OperacionCrear::ejecutar(Modelo *modelo){
	
	try{
		this->archivo->crear(this->formato_archivo);
		modelo->agregar_archivo(this->archivo);
		std::string mensaje = "Se creo correctamente el archivo "+this-> archivo->get_nombre() +" RES = 1";
		(*Logger::get_instance()) << mensaje;
		( Debug::get_instance() )->mostrar_mensaje(mensaje);
	}
	catch( ExcepSintaxisParser &e){
		delete this->archivo;
		std::string error = e.what();
		error.append("RES = 0");
		(*Logger::get_instance()) << error;
		( Debug::get_instance() )->mostrar_mensaje(error);
	}
	catch(ExcepCreandoArch &e){
		delete this->archivo;	
		std::string error = e.what();
		error.append("RES = 0");
		(*Logger::get_instance()) << error;
		( Debug::get_instance() )->mostrar_mensaje(error);
	}
	catch( ExcepBloqueTam &e){
		std::string error = e.what();
		error.append("RES = 0");
		delete this->archivo;
		(*Logger::get_instance()) << error;
		( Debug::get_instance() )->mostrar_mensaje(error);
	}
		
}

ArchivoDatos * OperacionCrear::get_archivo(){
	return this->archivo;
}

std::string OperacionCrear::get_formato(){
	return this->formato_archivo;	
}
